import logging
import random
import re

from flask import abort, jsonify
from flask import current_app
from flask import make_response
from flask import request
from flask import session

from info import constants
from info import redis_store, db
from info.libs.yuntongxun.sms import CCP

from info.models import User
from info.utils.captcha.captcha import captcha
from info.utils.response_code import RET
from . import passport_blue


@passport_blue.route('/logout', methods=['POST'])
def logout():
    # 点击退出时删除相应的session数据
    session.pop('user_id', None)
    session.pop('nick_name', None)
    session.pop('is_admin', False)
    return jsonify(errno=RET.OK, errmsg='退出成功')


# 实现登陆
@passport_blue.route('/login', methods=['POST'])
def login():
    # 一. 获取json数据
    json_data = request.json
    mobile = json_data.get('mobile')
    password = json_data.get('password')
    # 二. 校验参数
    if not all([mobile, password]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数输入有误')
    # 三. 逻辑处理
    # 1. 查询用户是否存在
    try:
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='mysql数据查询有误')
        # 从数据库取值，要判断它是否为空
    if not user or not user.check_passowrd(password):
        return jsonify(errno=RET.DATAERR, errmsg='用户或密码错误')
    # 使用session设置登陆
    session['user_id'] = user.id
    session['nick_name'] = user.nick_name

    return jsonify(errno=RET.OK, errmsg='登陆成功')


# 实现注册
@passport_blue.route('/register', methods=['POST'])
def register():
    # 一. 获取json数据
    json_data = request.json
    mobile = json_data.get('mobile')
    sms_code = json_data.get('sms_code')
    password = json_data.get('password')
    # 二. 校验参数
    if not all([mobile, sms_code, password]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数填写有误')
    # 校验手机号
    if not re.match(r'1[3-8][0-9]{9}', mobile):
        return jsonify(errno=RET.PARAMERR, errmsg='手机号码格式有误')
    # 三. 逻辑处理
    # 1. 校验短信验证码
    # 1.1 从redis中获取验证码内容
    try:
        real_sms_code = redis_store.get('sms_code_' + mobile)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='redis取值错误')
        # 从数据库取值，要判断它是否为空
    if not real_sms_code:
        return jsonify(errno=RET.NODATA, errmsg='验证码过期')
    # 1.2 对比验证码
    if real_sms_code != sms_code:
        return jsonify(errno=RET.PARAMERR, errmsg='验证码输入错误')
    # 1.3 对比成功后删除验证码
    try:
        redis_store.delete('sms_code_' + mobile)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='redis删除失败')
    # 2. 用户注册
    # 2.1 判断用户是否已注册过
    try:
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='mysql数据库查询错误')
        # 从数据库取值，要判断它是否为空
    if user:
        return jsonify(errno=RET.DATAEXIST, errmsg='用户已存在')
    # 2.2 保存用户信息至数据库
    user = User()
    user.mobile = mobile
    user.nick_name = mobile
    user.password = password
    # 提交数据库
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='mysql数据库提交失败')
    # 2.3 设置session实现登陆
    session['user_id'] = user.id
    session['nick_name'] = user.nick_name
    return jsonify(errno=RET.OK, errmsg='注册成功')


@passport_blue.route('/sms_code', methods=['POST'])
def sms_code():
    '''发送短信验证码'''
    # 1. 获取json数据
    json_data = request.json
    image_code_id = json_data.get('image_code_id')
    image_code = json_data.get('image_code')
    mobile = json_data.get('mobile')
    # 2. 校验参数
    if not all([image_code, image_code_id, mobile]):
        return jsonify(errno=RET.PARAMERR, errmsg='填写有误')
    if not re.match(r'1[3-8][0-9]{9}', mobile):
        return jsonify(errno=RET.PARAMERR, errmsg='手机号码格式有误')
    # 3. 校对图片验证码
    try:
        # 3.1 从redis获取图片验证码内容
        real_image_code = redis_store.get('image_code_id_' + image_code_id)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='redis读取验证码失败')
    # 从数据库取值，要判断它是否为空
    if not real_image_code:
        return jsonify(errno=RET.NODATA, errmsg='验证码过期')
    try:
        # 3.2 进行保存后删除
        redis_store.delete('image_code_id_' + image_code_id)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='删除失败')
    # 3.3 将两边内容都降为小写再进行比较
    if image_code.lower() != real_image_code.lower():
        return jsonify(errno=RET.PARAMERR, errmsg='图片验证码输入错误')
    # 4. 发送短信
    try:
        # 4.1 判断用户是否已注册
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='mysql查询失败')
    if user:
        return jsonify(errno=RET.DATAEXIST, errmsg='用户已存在')
    # 4.2 生成6位数的验证码
    sms_code_str = '%06d' % random.randint(0, 999999)
    current_app.logger.info(sms_code_str)
    try:
        # 4.3 使用redis保存验证码
        redis_store.setex('sms_code_' + mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code_str)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='redis数据库保存出错')
    # 4.4 调用第三方发送验证码短信
    result = CCP().send_template_sms(mobile, [sms_code_str, 5], 1)
    if result != '000000':
        return jsonify(errno=RET.THIRDERR, errmsg="发送短信验证码失败")
    return jsonify(errno=RET.OK, errmsg='发送短信验证码成功')


@passport_blue.route('/image_code')
def image_code():
    '''
    1. 获取参数
    2. 生成验证码
    3. 保存当前验证码
    4. 响应返回
    '''
    # 获取参数
    image_code_id = request.args.get('image_code_id')
    if not image_code_id:
        abort(403)
    # 生成验证码
    name, text, image_data = captcha.generate_captcha()
    # 保存当前验证码
    try:
        redis_store.setex('image_code_id_' + image_code_id, constants.IMAGE_CODE_REDIS_EXPIRES, text)
    except Exception as e:
        logging.error(e)
        return abort(500)
    # 返回给浏览器
    resp = make_response(image_data)
    resp.headers['Content-Type'] = 'image/jpg'
    return resp
